package com.xq.model.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xq.config.properties.ManageProperties;
import com.xq.config.properties.MusicProperties;
import com.xq.model.dto.PostStationStateDTO;
import com.xq.model.dto.StationStateDTO;
import com.xq.model.element.StationStateTxtEle;
import com.xq.model.entity.TBaseDataRecord;
import com.xq.model.entity.TBaseStationState;
import com.xq.model.mapper.TBaseStationStateMapper;
import com.xq.model.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xq.model.struct.UtilStruct;
import com.xq.model.utils.ParentUtils;
import com.xq.model.vo.DataRecordAddVo;
import com.xq.model.vo.DataRecordEditVo;
import com.xq.utils.*;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 站点状态信息表 服务实现类
 * </p>
 *
 * @author xu
 * @since 2021-08-31
 */
@Service
public class TBaseStationStateServiceImpl extends ServiceImpl<TBaseStationStateMapper, TBaseStationState> implements ITBaseStationStateService {
    @Resource
    private ParentUtils parentUtils;
    @Resource
    private MusicProperties musicProperties;
    @Resource
    private AsyncService asyncService;
    @Resource
    private ITBaseStationInfoService stationInfoService;
    @Resource
    private ManageProperties manageProperties;
    @Resource
    private UtilStruct utilStruct;
    @Resource
    private TBaseStationStateMapper stationStateMapper;
    @Resource
    private ITBaseDataRecordService dataRecordService;
    @Resource
    private DataTransferService dataTransferService;

    @Override
    public void againGetStationState(int nDay) throws IllegalAccessException, IOException, URISyntaxException {

        List<TBaseDataRecord> dataRecords = dataRecordService.missReportByTypeLeDay("2", nDay);

        if(dataRecords==null||dataRecords.size()==0){
            return;
        }

        for (TBaseDataRecord dataRecord : dataRecords) {
            // 如果存在未上报的情况
            if(dataRecord.getMissReportStationNum()>0){
                // 获取未上报的id 并且转为集合
                List<String> missIdList = Stream.of(dataRecord.getMissReportStationIdCList().split(",")).collect(Collectors.toList());
                // 请求获取数据
                List<StationStateTxtEle> eleList = requestStationState(dataRecord.getTimes());
                // 如果不存在 那就下一个吧
                if(eleList == null || eleList.size() == 0){
                    continue;
                }
                // 获取未上报的所有集合
                System.out.println("获取集合数："+eleList.size());
                List<StationStateTxtEle> newEleList = new ArrayList<>();
                // 判断是属于未上报的
                eleList.forEach(stationStateTxtEle -> {
                    // 如果包含
                    if(missIdList.contains(stationStateTxtEle.getStation_Id_C())){
                        newEleList.add(stationStateTxtEle);
                    }
                });
                // 3 表示超时状态
                List<TBaseStationState> stationStateList = byEleList(newEleList,dataRecord.getRequestNum(),"3");
                DataRecordEditVo editVo = new DataRecordEditVo();
                editVo.setStationStateList(stationStateList);
                editVo.setTimes(dataRecord.getTimes());
                // 2表示站点状态
                editVo.setDataType("2");
                // 将对象的idc 提取出来形成新集合
                List<String> overTimeIdList = stationStateList.stream().map(TBaseStationState::getStationIdC).collect(Collectors.toList());
                editVo.setOverTimeStationIdCList(overTimeIdList);
                // 就去存 不要犹豫
                dataRecordService.updateDataRecord(editVo);
            }
        }
    }

    @Override
    public void badState(List<TBaseStationState> stationStateList, String type) throws IOException {
        // 缺报的情况 由于数据库暂时没有这条数据 所以直接新增
        if("2".equals(type)){
            saveBatch(stationStateList);
            // 发送数据给云端
            postStationState(stationStateList);
        }
        // 超时报的情况 由于这条数据本身是缺报 故要查询出来
        if("3".equals(type)){
            for (TBaseStationState stationState : stationStateList) {
                LambdaQueryWrapper<TBaseStationState> lqw = Wrappers.lambdaQuery();
                // 根据访问轮次以及区站号去查
                lqw
                        .eq(true,TBaseStationState::getRequestNum,stationState.getRequestNum())
                        .eq(true,TBaseStationState::getStationIdC,stationState.getStationIdC());
                Long stateId = getOne(lqw).getId();
                stationState.setId(stateId);
                stationState.setStateType("3");
            }
            // 变成修改
            updateBatchById(stationStateList);
        }
    }

    @Override
    public void postOverStationState(List<TBaseStationState> stationStateList) throws IOException {
        List<PostStationStateDTO> stateDTOList = utilStruct.entityListToDtoList(stationStateList);
        String jsonStr = JSON.toJSONString(stateDTOList);
        HttpUtils.sendPostJson(manageProperties.getHost()+manageProperties.getOverStationStatePath(),jsonStr);
        // 记得把要素传输统计也一起送过去 2代表站点状态
        dataTransferService.postDataTransfer("2");
    }

    @Override
    public void postStationState(List<TBaseStationState> stationStateList) throws IOException {
        List<PostStationStateDTO> stateDTOList = utilStruct.entityListToDtoList(stationStateList);
        System.out.println("提交给云端的集合数："+stateDTOList.size());
        String jsonStr = JSON.toJSONString(stateDTOList);
        HttpUtils.sendPostJson(manageProperties.getHost()+manageProperties.getStationStatePath(),jsonStr);
        // 记得把要素传输统计也一起送过去 2代表站点状态
        dataTransferService.postDataTransfer("2");
    }

    @Override
    public void getStationState(String times) throws IllegalAccessException, IOException, URISyntaxException {
        // 请求获取数据
        List<StationStateTxtEle> eleList = requestStationState(times);

        // 没查到就算了
        if(eleList==null || eleList.size() ==0){
            return;
        }
        // 获取本地所有的站点号
        List<String> allStationIdCList =stationInfoService.allStationIdC();
        List<StationStateTxtEle> newEleList = new ArrayList<>();
        // 判断是属于本地的
        eleList.forEach(stationStateTxtEle -> {
            // 如果包含
            if(allStationIdCList.contains(stationStateTxtEle.getStation_Id_C())){
                newEleList.add(stationStateTxtEle);
            }
        });
        // 没有本地的就算了
        if(newEleList.size() ==0){
            return;
        }
        // 获取所有的集合
        System.out.println("获取集合数："+eleList.size());

        // 获取访问轮次
        long requestNum = stationStateMapper.selectMaxRequestNum() == null ? 0L : stationStateMapper.selectMaxRequestNum();
        // 自加1
        requestNum++;

        // 1 表示正常状态
        List<TBaseStationState> stationStateList = byEleList(newEleList,requestNum,"1");

        System.out.println("获取的有效集合数："+stationStateList.size());
        // 获取的有效集合数大于0
        if(stationStateList.size()>0){
            // 保存所有
            saveBatch(stationStateList);
            // 保存到数据记录
            saveDataRecord(times,stationStateList,requestNum);

            // 发送数据给云端
            postStationState(stationStateList);
        }
    }

    private List<TBaseStationState> byEleList(List<StationStateTxtEle> newEleList,Long requestNum,String stateType){
        List<TBaseStationState> stationStateList = new ArrayList<>();
        // 得到的文件路径再次请求
        for (StationStateTxtEle stationStateTxtEle : newEleList) {
            // 路径不为空就请求
            if(StrUtil.isNotBlank(stationStateTxtEle.getFile_URL())){
                // 异步执行请求
                CompletableFuture<TBaseStationState> completableFuture = asyncService.byUrl(stationStateTxtEle.getFile_URL());
                try {
                    // 异步执行的不为空 就加入
                    if(completableFuture.get()!=null){
                        TBaseStationState stationState = completableFuture.get();
                        stationState.setRequestNum(requestNum);
                        // 设置站点数据的状态
                        stationState.setStateType(stateType);
                        stationState.setReceiveTime(DateUtils.strToDatePlusHours(8,stationStateTxtEle.getRYMDHM()));
                        stationStateList.add(stationState);
                    }
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
            }
        }
        return stationStateList;
    }

    /**
     * 根据时间请求数据
     * @param times
     */
    private List<StationStateTxtEle> requestStationState(String times) throws IllegalAccessException, IOException, URISyntaxException {
        StationStateDTO stationStateDTO = new StationStateDTO();
        // 初始化
        parentUtils.init(stationStateDTO,musicProperties);
        stationStateDTO.setInterfaceId("getSurfFileByTime");
        stationStateDTO.setDataCode("SURF_REGSTATION_STATEINFO_TXT");
        stationStateDTO.setElements(ClassUtil.objectToString(new StationStateTxtEle()));
        stationStateDTO.setTimes(times);
        // 暂时不限制
        //stationStateDTO.setLimitCnt("10");
        // 暂时不排序
        //stationStateDTO.setOrderBy("");
        stationStateDTO.setDataFormat("json");

        // 将对象转成map
        Map<String, String> signMap = MapUtil.beanToMap(stationStateDTO);
        // 获取签名
        String sign = SignGenUtil.getSign(signMap);

        stationStateDTO.setSign(sign);

        // 获取请求参数
        String params = MapUtil.toParamsFromMap(MapUtil.beanToMap(stationStateDTO));
        // 获取返回数据 jsonArray
        JSONArray restArray = HttpUtils.sendGetToList(musicProperties, params);
        // 不为空继续操作
        if(restArray == null){
            System.out.println("为什么又不上传数据");
            return null;
        }
        // 转成list对象
        return JsonUtils.jsonToList(restArray.toJSONString(),StationStateTxtEle.class);
    }

    private void saveDataRecord(String times,List<TBaseStationState> stationStateList, Long requestNum) throws IOException {
        DataRecordAddVo recordAddVo = new DataRecordAddVo();
        // 2 代表站点设备的状态
        recordAddVo.setDataType("2");
        recordAddVo.setTimes(times);

        // 设置访问轮次
        recordAddVo.setRequestNum(requestNum);

        List<String> realReportStationIdCList = new ArrayList<>();
        stationStateList.forEach(x -> realReportStationIdCList.add(x.getStationIdC()));
        // 设置已上报的idc 集合
        recordAddVo.setRealReportStationIdCList(realReportStationIdCList);
        // 保存一下咯
        dataRecordService.addDataRecord(recordAddVo);
    }
}
